/**
 * @file ltc2943.h
 * @author 蔡云蔚 (you@domain.com)
 * @brief 库仑计LTC2943
 * @brief 注意：
 * @brief 本人实验中发现，读取只能从开头的00寄存器读取！！
 * @brief 无论读取时序中发送的寄存器值！
 * @brief 非常奇怪！！！！
 * @version 0.1
 * @date 2024-08-29
 * 
 * @copyright Copyright (c) 2024
 * 
 */

#pragma once

#include "i2c.h"
#include "main.h"
#include "gpio.h"

#include "memxx_supplement.h"

static constexpr float BATTERY_CAPACITY = 1000.0;//电池容量单位：毫安时 mAh 
static constexpr float R_SENSE = 50.0;//检测电阻大小 单位：毫欧

class LTC2943
{
private:
  static LTC2943 only;//静态实例
public:
  /**
   * @brief Get the Instance object
   * 
   * @return LTC2943& 
   */
  static LTC2943& getInstance();
private:
  /**
   * @brief Construct a new LTC2943 object
   * @note 私有化构造函数，防止外部直接创建实例
   */
  LTC2943();
private:
  /**
   * @brief Destroy the LTC2943 object
   * @note 私有化析构函数 
   */
  ~LTC2943(){};
private:
  /**
   * @brief Construct a new LTC2943 object
   * @note 禁用拷贝构造
   */
  LTC2943(const LTC2943&) = delete;
private:
  /**
   * @brief 赋值构造
   * @return LTC2943& 
   * @note 禁用掉
   */
  LTC2943& operator=(const LTC2943&) = delete;


 
private:
  /**
   * @brief 使用的I2C句柄
   * @note 使用其它IIC口请修改
   */
  I2C_HandleTypeDef& LTC2943_I2C_Handle = hi2c1;
  /**
   * @brief IIC初始化函数
   * @note 使用其它IIC口请修改
   */
  void (*LTC2943_I2C_INIT)(void) = MX_I2C1_Init;

  uint8_t LTC2943_ADDRESS = 0xC8;//7位IIC地址 1100 100  0（补）

private:
  uint16_t Prescaler_record = 4096;//用来记录设置的分频器值

  float q_LSB_record = 0.34;//记录一量化单位代表的电量 单位：毫安时 mAh
public:
  uint8_t Control_Register_record = 0X3C;//用来记录控制寄存器的设置
public:
    /**
     * @brief 库仑计初始化
     * 
     */
    void Init(void);
public:
    /**
     * @brief 读取库仑计的状态寄存器
     * 
     * @param theStatus 状态的保存位置
     * @return HAL_StatusTypeDef 函数执行情况
     */
    HAL_StatusTypeDef Status_Read(uint8_t* theStatus);
public:
    /**
     * @brief 配置LTC2943的控制寄存器
     * 
     * @param config 配置项 用|连接四个配置项
     * @return HAL_StatusTypeDef 
     * @note namespace LTC2943_B 中的选项
     */
    HAL_StatusTypeDef Set_Control_Register(uint8_t config);
public:    
    /**
     * @brief 读取库仑计所有寄存器
     * 
     * @param theBuffer 
     * @return HAL_StatusTypeDef 
     */
    HAL_StatusTypeDef All_Read(uint8_t* theBuffer);
public:
    /**
     * @brief LTC2943累计电荷写入
     * 
     * @param Accumulated_Charge 积累的电荷 单位：毫安时 mAh
     * @return HAL_StatusTypeDef 
     */
    HAL_StatusTypeDef Accumulated_Charge_Set(float Accumulated_Charge);
public:
    /**
     * @brief 计算累计电荷
     * 
     * @param Accumulated_Charge_Buffer 
     * @return float 
     */
    float Accumulated_Charge_get(uint8_t* Accumulated_Charge_Buffer);
public:
    /**
     * @brief 计算电压
     * 
     * @param Voltage_Buffer 
     * @return float 
     */
    float Voltage_get(uint8_t* Voltage_Buffer);
public:
    /**
     * @brief 计算电流
     * 
     * @param Current_Buffer 
     * @return float 
     */
    float Current_get(uint8_t* Current_Buffer);
public:
    /**
     * @brief 计算温度
     * 
     * @param Temperature_Buffer 
     * @return float 
     */
    float Temperature_get(uint8_t* Temperature_Buffer);
};
extern LTC2943& ltc2943;//实例化的库仑计引用




/**
 * @brief LTC2943控制寄存器指令罗列
 * @note 使用时请按位或 |
 * 
 */
namespace LTC2943_B
{
    //B[7:6] ADC Mode
    static constexpr uint8_t ADC_Automatic = 0XC0;//11 00 0000 连续执行电压，电流和温度转换
    static constexpr uint8_t ADC_Scan      = 0X80;//10 00 0000 电压、电流和温度每10秒转换一次
    static constexpr uint8_t ADC_Manual    = 0X40;//01 00 0000 执行电压、电流和温度的单次转换，然后休眠
    static constexpr uint8_t ADC_Sleep     = 0X00;//00 00 0000 休眠

    //B[5:3] Prescaler M
    static constexpr uint8_t Prescaler_1        = 0X00;//00_00 0_000
    static constexpr uint8_t Prescaler_4        = 0X08;//00_00 1_000
    static constexpr uint8_t Prescaler_16       = 0X10;//00_01 0_000
    static constexpr uint8_t Prescaler_64       = 0X18;//00_01 1_000
    static constexpr uint8_t Prescaler_256      = 0X20;//00_10 0_000
    static constexpr uint8_t Prescaler_1024     = 0X28;//00_10 1_000
    static constexpr uint8_t Prescaler_4096     = 0X30;//00_11 0_000
    static constexpr uint8_t Prescaler_Default  = 0X38;//00_11 1_000 也是4096

    //B[2:1] ALCC Configure
    static constexpr uint8_t ALCC_Alert           = 0X04;//0000 0 10 0 启用警报功能。引脚变成逻辑输出
    static constexpr uint8_t ALCC_Charge_Complete = 0X02;//0000 0 01 0 警报引脚成为逻辑输入，并接受电荷完全反转信号(例如，来自充电器)，将累计电荷寄存器(C,D)设置为FFFFh。
    static constexpr uint8_t ALCC_Pin_disabled    = 0X00;//0000 0 00 0 关闭警报引脚
    static constexpr uint8_t ALCC_Not_allowed     = 0X06;//0000 0 11 0 不使用警报

    //B[0] Shutdown
    static constexpr uint8_t Shutdown_False = 0X00;//0000 000 0 正常工作
    static constexpr uint8_t Shutdown_True  = 0X01;//0000 000 1 将关闭LTC2943的模拟部分，任何流动的电荷都不会被测量，寄存器中的值被保留。
}











// /**
//  * @brief LTC2943电压读取
//  * 
//  * @param Voltage 电压的保存位置 单位：伏特 V
//  * @return HAL_StatusTypeDef 
//  */
// HAL_StatusTypeDef LTC2943_Voltage_Read(float* Voltage);

// /**
//  * @brief LTC2943电流读取
//  * 
//  * @param Current 电流的保存位置 单位：安培 A
//  * @return HAL_StatusTypeDef 
//  */
// HAL_StatusTypeDef LTC2943_Current_Read(float* Current);

// /**
//  * @brief LTC2943温度读取
//  * 
//  * @param Temperature 温度的保存位置 单位：摄氏度 ℃
//  * @return HAL_StatusTypeDef 
//  */
// HAL_StatusTypeDef LTC2943_Temperature_Read(float* Temperature);

// /**
//  * @brief LTC2943累计电荷读取
//  * 
//  * @param Accumulated_Charge 积累的电荷的保存位置 单位：毫安时 mAh
//  * @return HAL_StatusTypeDef 
//  */
// HAL_StatusTypeDef LTC2943_Accumulated_Charge_Read(float* Accumulated_Charge);

